package com.willow.liutige.aspect;

import com.jd.platform.hotkey.client.callback.JdHotKeyStore;
import com.willow.liutige.annotation.HotKeyCache;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

@Aspect
@Component
@Slf4j
public class HotKeyCacheAspect {
    private final SpelExpressionParser spelParser = new SpelExpressionParser();

    public HotKeyCacheAspect() {
        // 启动时检查是否打印
        log.info("HotKeyCacheAspect initialized!");
    }

    @Around("@annotation(hotKeyCache)")
    public Object around(ProceedingJoinPoint joinPoint, HotKeyCache hotKeyCache) throws Throwable {
        // 1. 构建缓存key
        String cacheKey = buildCacheKey(joinPoint, hotKeyCache);
        log.debug("Checking hot key: {}", cacheKey);

        // 2. 非强制更新模式：先查缓存
        if (!hotKeyCache.forceUpdate()) {
            boolean isHot = JdHotKeyStore.isHotKey(cacheKey);
            log.debug("Is hot key: {}", isHot);

            if (isHot) {
                Object cachedValue = JdHotKeyStore.get(cacheKey);
                log.debug("Cached value: {}", cachedValue);
                if (cachedValue != null) {
                    return cachedValue;
                }
            }
        }

        // 3. 执行原方法
        Object result = joinPoint.proceed();

        // 4. 缓存结果
        if (result != null || hotKeyCache.cacheNull()) {
            log.debug("Setting cache for key: {}", cacheKey);
            if (hotKeyCache.forceUpdate()) {
                JdHotKeyStore.forceSet(cacheKey, result);
            } else {
                JdHotKeyStore.smartSet(cacheKey, result);
            }
        }

        return result;
    }

    private String buildCacheKey(ProceedingJoinPoint joinPoint, HotKeyCache hotKeyCache) {
        if (hotKeyCache.keyParam().isEmpty()) {
            return hotKeyCache.keyPrefix();
        }

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Object[] args = joinPoint.getArgs();

        StandardEvaluationContext context = new StandardEvaluationContext();
        context.setVariable("args", args);
        String[] parameterNames = signature.getParameterNames();
        for (int i = 0; i < parameterNames.length; i++) {
            context.setVariable(parameterNames[i], args[i]);
        }

        Expression expression = spelParser.parseExpression(hotKeyCache.keyParam());
        Object keyValue = expression.getValue(context);

        return hotKeyCache.keyPrefix() + keyValue;
    }
}